package com.zy.cat.service.impl;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

import javax.transaction.Transactional;

import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.annotations.CreationTimestamp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.stereotype.Service;

import com.alibaba.fastjson.parser.ParseContext;
import com.zy.cat.common.annotation.RedisEvicts;
import com.zy.cat.common.annotation.RedisEvicts.RedisEvict;
import com.zy.cat.common.annotation.RedisSingle;
import com.zy.cat.common.utils.AesEncryptUtils;
import com.zy.cat.common.utils.DateAPIUtils;
import com.zy.cat.common.utils.SpringContextUtil;
import com.zy.cat.common.utils.TJKUtils;
import com.zy.cat.dao.Dao;
import com.zy.cat.entity.dev.act.APPActDBHistory;
import com.zy.cat.entity.dev.act.CatDailyDrawAwardeeOrder;
import com.zy.cat.entity.dev.act.CatDailyDrawDetail;
import com.zy.cat.entity.dev.act.CatDailyDrawHistory;
import com.zy.cat.entity.dev.act.CatDailyDrawPrizeInfo;
import com.zy.cat.entity.dev.act.CatDailyDrawResult;
import com.zy.cat.entity.dev.act.repository.APPActDBHistoryRepository;
import com.zy.cat.entity.dev.act.repository.CatDailyDrawAwardeeOrderRepository;
import com.zy.cat.entity.dev.act.repository.CatDailyDrawDetailRepository;
import com.zy.cat.entity.dev.act.repository.CatDailyDrawHistoryRepository;
import com.zy.cat.entity.dev.act.repository.CatDailyDrawPrizeInfoRepository;
import com.zy.cat.entity.dev.act.repository.CatDailyDrawResultRepository;
import com.zy.cat.entity.dev.act.resp.APPActDBHistoryResp;
import com.zy.cat.entity.dev.act.resp.APPActDBInfoResp;
import com.zy.cat.entity.dev.act.resp.APPActDBInfoResp.Goods;
import com.zy.cat.entity.dev.act.resp.CatDailyDrawDetailResp;
import com.zy.cat.entity.dev.act.resp.CatDailyDrawListResp;
import com.zy.cat.entity.dev.act.resp.CatDailyDrawListResp.Prize;
import com.zy.cat.entity.resp.Pages;
import com.zy.cat.entity.resp.RSPE;
import com.zy.cat.entity.resp.ResultPage;
import com.zy.cat.service.AsyncService;
import com.zy.cat.service.CacheService;
import com.zy.cat.service.CatDevActService;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class CatDevActServiceImpl implements CatDevActService {

	/**
	 * 每日弹窗记录,只缓存一天，index：0.天天抽奖活动
	 */
	private final String POPUP_RECORD_DAILY_KEY = "CAT_POPUP_RECORD_DAILY_KEY";

	@Autowired
	Dao<APPActDBHistoryResp> ccdao;

	@Autowired
	Dao<Goods> cgdao;

	@Autowired
	Dao<Integer> intDao;

	@Autowired
	CacheService cacheService;

	@Autowired
	AsyncService asyncService;

	@Autowired
	APPActDBHistoryRepository aPPActDBHistoryRepository;

	@Autowired
	CatDailyDrawPrizeInfoRepository dailyDrawPrizeInfoRepository;

	@Autowired
	CatDailyDrawHistoryRepository dailyDrawHistoryRepository;

	@Autowired
	CatDailyDrawDetailRepository dailyDrawDetailRepository;

	@Autowired
	CatDailyDrawResultRepository dailyDrawResultRepository;

	@Autowired
	CatDailyDrawAwardeeOrderRepository dailyDrawAwardeeOrderRepository;

	@Autowired
	@Qualifier("redis7")
	RedisTemplate<String, Long> redis7;

	@Autowired
	@Qualifier("redis17")
	RedisTemplate<String, Object> redis17;

	@Override
	public APPActDBInfoResp getDbInfo(String pid) {
		List<APPActDBInfoResp.Goods> goods = cacheService.getDbGoods(pid);
		List<APPActDBInfoResp.Goods> list = new ArrayList<APPActDBInfoResp.Goods>();

		if (goods != null) {
			list = goods.stream().map(mapper -> {
				if (mapper.getQstatus() == 1 && mapper.getQids().split(",").length > 2) {
					// 状态（0.参与人数已满、1.进行中、2.参与次数已达上限）
					mapper.setQstatus(2);
				}
				int cindex = cacheService.getMaxCindex(mapper.getSid());
				mapper.setCindex(cindex);
				return mapper;
			}).collect(Collectors.toList());
		}

		APPActDBHistoryResp lcountEntity = ccdao.selectOne(new APPActDBHistoryResp(pid), "getLastQCount");
		int lcount = 0;
		long lasts = 0;

		/* 第一次请求 */
		if (lcountEntity == null) {
			lcount = 5;
		} else {
			lcount = 5 - lcountEntity.getCindex();

			/* 5上次全部已用完 */
			if (lcount == 5) {
				/* 未到达刷新时间 */
				if (TJKUtils.parse2LocalDateTime(lcountEntity.getCtime()).plusHours(4).isAfter(LocalDateTime.now())) {
					String etime = TJKUtils.parse2LocalDateTime(lcountEntity.getCtime()).plusHours(4)
							.format(DateAPIUtils.FORMATTER_YYYYMMDDHHMMSS);
					lasts = TJKUtils.secondsInterval(TJKUtils.DateTime(), etime);
					lasts = lasts < 0 ? 0 : lasts;
					lcount = 0;
					log.info("-start->" + TJKUtils.DateTime() + "-end-->" + etime + "-seconds-->" + lasts);
				}
			}

//			if(TJKUtils.parse2LocalDateTime(lcountEntity.getCtime()).plusHours(4).isAfter(LocalDateTime.now())) {
//				String etime = TJKUtils.parse2LocalDateTime(lcountEntity.getCtime()).plusHours(4)
//						.format(TJKUtils.FORMATTER_YYYYMMDDHHMMSS);
//				lasts = TJKUtils.secondsInterval(TJKUtils.DateTime(), etime);
//				lasts=lasts<0?0:lasts;
//				log.info("-start->" + TJKUtils.DateTime() + "-end-->" + etime + "-seconds-->" + lasts);
//			}

//			if (lcount == 0) {
//				String etime = TJKUtils.parse2LocalDateTime(lcountEntity.getCtime()).plusHours(4)
//						.format(TJKUtils.FORMATTER_YYYYMMDDHHMMSS);
//				lasts = TJKUtils.secondsInterval(TJKUtils.DateTime(), etime);
//				lasts=lasts<0?0:lasts;
//				log.info("-start->" + TJKUtils.DateTime() + "-end-->" + etime + "-seconds-->" + lasts);
//			}
		}
		return new APPActDBInfoResp(lasts, lcount, list);
	}

	@Override
	@RedisSingle(key = "CAT_CJ_SINGLE_+#sid+_+#cindex", waitExpire = 1000)
	@RedisEvict(db = 7, rtype = 2, key = "CAT_CJ_GOODS_LIST", hashKeys = { "+#pid" })
	public RSPE<Object> getDbStart(int cindex, String sid, String pid) {

		Goods goods = cgdao.selectOne(new APPActDBHistoryResp(sid, cindex), "getGoodsCJInfo");
		// 商品为null或商品的已参与人数大于等于最多参与人数
		if (goods == null || goods.getYcount() >= goods.getDcount()) {
			return new RSPE<Object>(-4, "本期参与人数已达上限，请稍后重试！");
		}
		// 剩余免费抽奖次数
		APPActDBHistoryResp lcountEntity = ccdao.selectOne(new APPActDBHistoryResp(pid), "getLastQCount");
		int lcount = 0;
		if (lcountEntity != null) {
			lcount = 5 - lcountEntity.getCindex();

			/* 5.上次全部已用完 */
			if (lcount == 5) {
				/* 未到达刷新时间 */
				if (TJKUtils.parse2LocalDateTime(lcountEntity.getCtime()).plusHours(4).isAfter(LocalDateTime.now())) {
					return new RSPE<Object>(-5, "抽奖次数已用完！请稍后重试！");
				}
			}
		}
		// 商品参与次数
		APPActDBHistoryResp gcounts = ccdao.selectOne(new APPActDBHistoryResp(sid, pid, cindex), "getGoodsQCount");
		if (gcounts != null && gcounts.getCindex() >= 3) {
			return new RSPE<Object>(-6, "本商品参与次数已达上限，请稍后重试！");
		}
		// 个人劵（获取抽奖商品最大劵值）+1
		long qid = cacheService.getMaxQid(sid, cindex) + 1;
		String ctime = TJKUtils.DateTime();
		APPActDBHistory history = new APPActDBHistory(sid, pid, cindex, qid, 1, ctime, ctime);
		if (aPPActDBHistoryRepository.saveAndFlush(history) != null) {
			String key = "CAT_CJ_GOODS_MAX_QID", hashKey = sid + "_" + cindex;
			redis7.opsForHash().increment(key, hashKey, 1);
//			redis7.opsForHash().delete("CAT_CJ_GOODS_LIST", pid);
			int zjds = 77;
			if (goods.getDcount() <= 10) {
				zjds = 7;
			} else if (goods.getDcount() <= 100) {
				zjds = 17;
			}

			if (goods.getYcount() > goods.getDcount() / 5
					&& (goods.getYcount() + 2 < goods.getDcount() && goods.getYcount() % zjds == 0)) {
				long robot_qid = qid + 1;
				APPActDBHistory robot = new APPActDBHistory(sid, "1000000001", cindex, robot_qid, 0, ctime, ctime);
				robot.setPhone(TJKUtils.getRandomPhone());
				if (aPPActDBHistoryRepository.saveAndFlush(robot) != null) {
					redis7.opsForHash().increment(key, hashKey, 1);
				}
			}

			/* 参与人数已满，准备开奖 */
			if ((goods.getYcount() + 1) >= goods.getDcount()) {
				/* 删除商品期数缓存 */
				redis7.opsForHash().delete("CAT_CJ_GOODS_MAX_CINDEX", sid);
				redis17.opsForList().leftPush("CAT_CJ_QIDS_FULL", sid + "_" + cindex);
			}
			return new RSPE<Object>(qid);
		}
		return new RSPE<Object>(-7, "参与人数过多，请稍后重试！");
	}

	@Override
	public ResultPage<APPActDBHistoryResp> getDbList(String pid, Integer dstatus, Pages pages) {
		return ccdao.listAndPages(new APPActDBHistoryResp(pid), pages);
	}

	@Override
	public ResultPage<APPActDBHistoryResp> getDbRList(String pid, Pages pages) {
		return ccdao.listAndPages(new APPActDBHistoryResp(pid), "listAndPages2", pages);
	}

	@Override
	public CatDailyDrawListResp getDailyDrawInfo(String pid) {
		CatDailyDrawListResp resp = new CatDailyDrawListResp();
		if (StringUtils.isEmpty(pid)) {
			pid = "111111";
		} else {
			// 设置是否展示弹窗
			resp.setIsFirst(getPopupStatus(0, pid));
		}
		List<CatDailyDrawListResp.Prize> prizeList = cacheService.dailyDrawPrizeList(pid);
		if (prizeList == null || prizeList.isEmpty()) {
			// 查询抽奖奖品信息,新建抽奖活动
			if (createDailyDrawList() == null) {
				return null;
			}
			prizeList = cacheService.dailyDrawPrizeList(pid);
		}
		resp.setList(prizeList);

		// 获取用户剩余次数
		Integer selectOne = intDao.selectOne(new CatDailyDrawDetailResp(pid), "getDailyDrawCount");
		resp.setSurplusCount(3 - (selectOne == null ? 0 : selectOne));

		return resp;
	}

	/**
	 * 获取弹窗ID
	 * 
	 * @date 2019-12-10 10:34:55
	 * @param index   0.天天抽奖活动
	 * @param openNum
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private int getPopupStatus(int index, String pid) {
		// 是否展示
		Object object = redis7.opsForHash().get(POPUP_RECORD_DAILY_KEY, pid);
		List<Integer> showPopupList = null;
		Integer isShow = null;
		if (object instanceof List) {
			showPopupList = (List<Integer>) object;
		} else {
			isShow = (Integer) object;
		}
		if (showPopupList == null || showPopupList.size() < 1) {
			showPopupList = new ArrayList<>(1);
			showPopupList.add(null);
		}
		isShow = showPopupList.get(index) == null ? isShow : showPopupList.get(index);
		Integer temp = isShow;
		if (isShow == null) {
			isShow = 1;
		}
		showPopupList.set(index, isShow);
		// 如果不存在
		if (!redis7.hasKey(POPUP_RECORD_DAILY_KEY)) {
			redis7.opsForHash().put(POPUP_RECORD_DAILY_KEY, pid, showPopupList);
			// 设置过期时间为一天
			Date date = Date.from(LocalDateTime.now().with(LocalTime.MAX).atZone(ZoneId.systemDefault()).toInstant());
			redis7.expireAt(POPUP_RECORD_DAILY_KEY, date);
		} else if (!isShow.equals(temp)) {
			// 数据发生变化是进行更新
			redis7.opsForHash().put(POPUP_RECORD_DAILY_KEY, pid, showPopupList);
		}
		return !isShow.equals(temp) ? 1 : 0;
	}

	/**
	 * 创建天天抽奖活动
	 * 
	 * @author lipengchao
	 * @date 2020-08-26 11:20:03
	 * @return
	 */
	private List<CatDailyDrawPrizeInfo> createDailyDrawList() {
		// TODO Auto-generated method stub
		List<CatDailyDrawPrizeInfo> list = dailyDrawPrizeInfoRepository.findByPrizeStatusOrderBySortAsc(1);
		if (list == null || list.isEmpty()) {
			return null;
		}
		List<CatDailyDrawHistory> collect = list.stream().map(obj -> {
			return CatDailyDrawHistory.builder().prizeId(obj.getId()).round(1).drawTotal(obj.getCondition())
					.drawStatus(0).drawNum(0).createTime(new Date()).build();
		}).collect(Collectors.toList());

		if (dailyDrawHistoryRepository.saveAll(collect) == null) {
			return null;
		}
		dailyDrawHistoryRepository.flush();
		return list;
	}

	@Override
	public ResultPage<Prize> getDailyDrawList(String pid, Integer type, Integer drawStatus, Integer pageNum,
			Integer pageSize) {
		// 默认已开奖
		if (drawStatus == null) {
			drawStatus = 1;
		}

		final String tempPid = StringUtils.isEmpty(pid) ? "111111" : pid;
		String key = pid + pageNum + pageSize;
		ResultPage<Prize> resultPage = cacheService.getDailyDrawList(key, pid, type, drawStatus, pageNum, pageSize);
		if (resultPage != null && resultPage.getList() != null) {
			resultPage.getList().forEach(obj -> {
				if (obj.getAwardeeInfo() != null && obj.getAwardeeInfo().size() > 0) {
					obj.getAwardeeInfo().forEach(item -> {
						item.setAwardeeName(AesEncryptUtils.decrypt(item.getAwardeeName()));
						if (tempPid.equals(item.getPid())) {
							// 标识用户已中奖
							obj.setIsWinPrize(1);
							obj.setOrderStatus(item.getDrawStatus());
						}
					});
				}
			});
		}
		if (resultPage == null) {
			resultPage = new ResultPage<>(pageNum, pageSize, 0, new ArrayList<>());
		}
		return resultPage;
	}

	@Override
	public CatDailyDrawDetailResp getDailyDrawDetail(String pid, Integer drawId) {
		// TODO Auto-generated method stub
		if (StringUtils.isEmpty(pid)) {
			pid = "111111";
		}
		String key = pid + drawId;
		CatDailyDrawDetailResp resp = cacheService.getDailyDrawDetail(key, pid, drawId);
		return resp;
	}

	@Override
	@RedisEvicts(before = false, evict = {
			@RedisEvicts.RedisEvict(rtype = 2, db = 7, key = "CAT_DAILY_DRAW_LIST", hashKeys = { "+#pid" }) })
	@Transactional
	public Integer addDailyDrawProbability(Integer drawId, String pid, CatDailyDrawHistory drawHistory,
			CatDailyDrawDetail drawDetail) {
		// 提升幸运值
		// 判断此用户是否已参与本轮抽奖
		Integer selectOne = intDao.selectOne(new CatDailyDrawDetailResp(drawId, pid), "getDailyDrawNumber");
		boolean isDrawPrize = false;
		if (selectOne == null || selectOne == 0) {
			drawHistory.setDrawNum(drawHistory.getDrawNum() + 1);
			if (drawHistory.getDrawNum() >= drawHistory.getDrawTotal()) {
				// 进行开奖
				isDrawPrize = true;
			}
			drawHistory.setUpdateTime(new Date());
			dailyDrawHistoryRepository.saveAndFlush(drawHistory);
		}
		// 随机生成本次幸运值

		int nextInt = RandomUtils.nextInt(5, 21);
		if (drawDetail == null) {
			drawDetail = new CatDailyDrawDetail(pid, drawId.longValue(), nextInt, 1, new Date());
		} else {
			drawDetail.setUpdateTime(new Date());
			drawDetail.setIncreaseCount(drawDetail.getIncreaseCount() + 1);
			drawDetail.setLuckyValue(drawDetail.getLuckyValue() + nextInt);
		}
		if (dailyDrawDetailRepository.saveAndFlush(drawDetail) == null) {
			return null;
		}

		// 进行开奖
		if (isDrawPrize) {
			asyncService.startDailyDraw(drawId);
		}
		return nextInt;
	}

	@Override
	@Transactional
	public CatDailyDrawAwardeeOrder receiveDailyDrawPrize(CatDailyDrawResult drawResult, String recipientName,
			String recipientPhone, String area, String address) {
		drawResult.setDrawStatus(2);
		drawResult.setUpdateTime(new Date());
		dailyDrawResultRepository.saveAndFlush(drawResult);
		CatDailyDrawAwardeeOrder awardeeOrder = dailyDrawAwardeeOrderRepository.findByPidAndDrawId(drawResult.getPid(),
				drawResult.getDrawId());
		if (awardeeOrder == null) {
			awardeeOrder = new CatDailyDrawAwardeeOrder();
			awardeeOrder.setCreateTime(new Date());
			awardeeOrder.setOrderStatus(0);
			awardeeOrder.setPid(drawResult.getPid());
			awardeeOrder.setDrawId(drawResult.getDrawId());
		} else {
			awardeeOrder.setUpdateTime(new Date());
		}
		awardeeOrder.setRecipientName(recipientName);
		awardeeOrder.setRecipientPhone(recipientPhone);
		awardeeOrder.setAddress(address);
		// 设置省市区
		String[] split = area.split(",");
		awardeeOrder.setProvince(split[0]);
		awardeeOrder.setCity(split[1]);
		awardeeOrder.setCounty(split[2]);
		// 保存一条订单记录
		return dailyDrawAwardeeOrderRepository.saveAndFlush(awardeeOrder);
	}
}
